From ab432bcd28596265e97eb062a19cbbbdc3d426f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 4 Nov 2020 22:56:03 +0200 Subject: [PATCH 02/25] [libcxx] Implement _FilesystemClock::now() and __last_write_time for windows Differential Revision: https://reviews.llvm.org/D91142 (cherry picked from commit 592d62352933d34af62334d172c6fc665933e0de) --- libcxx/src/filesystem/filesystem_common.h | 6 ++++++ libcxx/src/filesystem/operations.cpp | 23 +++++++++++++++++++++-- libcxx/src/filesystem/posix_compat.h | 17 +++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/libcxx/src/filesystem/filesystem_common.h b/libcxx/src/filesystem/filesystem_common.h index 8204e9a2e5f8..a4505171c3eb 100644 --- a/libcxx/src/filesystem/filesystem_common.h +++ b/libcxx/src/filesystem/filesystem_common.h @@ -437,7 +437,11 @@ public: } }; +#if defined(_LIBCPP_WIN32API) +using fs_time = time_util; +#else using fs_time = time_util; +#endif #if defined(__APPLE__) inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } @@ -456,6 +460,7 @@ inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; } #endif +#if !defined(_LIBCPP_WIN32API) inline TimeVal make_timeval(TimeSpec const& ts) { using namespace chrono; auto Convert = [](long nsec) { @@ -498,6 +503,7 @@ bool set_file_times(const path& p, std::array const& TS, return posix_utimensat(p, TS, ec); #endif } +#endif /* !_LIBCPP_WIN32API */ } // namespace } // end namespace detail diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp index 548a0273ce71..40a863db69a1 100644 --- a/libcxx/src/filesystem/operations.cpp +++ b/libcxx/src/filesystem/operations.cpp @@ -42,7 +42,7 @@ # define _LIBCPP_FILESYSTEM_USE_FSTREAM #endif -#if !defined(CLOCK_REALTIME) +#if !defined(CLOCK_REALTIME) && !defined(_LIBCPP_WIN32API) # include // for gettimeofday and timeval #endif @@ -567,7 +567,14 @@ const bool _FilesystemClock::is_steady; _FilesystemClock::time_point _FilesystemClock::now() noexcept { typedef chrono::duration __secs; -#if defined(CLOCK_REALTIME) +#if defined(_LIBCPP_WIN32API) + typedef chrono::duration __nsecs; + FILETIME time; + GetSystemTimeAsFileTime(&time); + TimeSpec tp = detail::filetime_to_timespec(time); + return time_point(__secs(tp.tv_sec) + + chrono::duration_cast(__nsecs(tp.tv_nsec))); +#elif defined(CLOCK_REALTIME) typedef chrono::duration __nsecs; struct timespec tp; if (0 != clock_gettime(CLOCK_REALTIME, &tp)) @@ -1121,6 +1128,17 @@ void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { using detail::fs_time; ErrorHandler err("last_write_time", ec, &p); +#if defined(_LIBCPP_WIN32API) + TimeSpec ts; + if (!fs_time::convert_to_timespec(ts, new_time)) + return err.report(errc::value_too_large); + detail::WinHandle h(p.c_str(), FILE_WRITE_ATTRIBUTES, 0); + if (!h) + return err.report(detail::make_windows_error(GetLastError())); + FILETIME last_write = timespec_to_filetime(ts); + if (!SetFileTime(h, nullptr, nullptr, &last_write)) + return err.report(detail::make_windows_error(GetLastError())); +#else error_code m_ec; array tbuf; #if !defined(_LIBCPP_USE_UTIMENSAT) @@ -1142,6 +1160,7 @@ void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { detail::set_file_times(p, tbuf, m_ec); if (m_ec) return err.report(m_ec); +#endif } void __permissions(const path& p, perms prms, perm_options opts, diff --git a/libcxx/src/filesystem/posix_compat.h b/libcxx/src/filesystem/posix_compat.h index 3eec4634e929..7caf9d28b49d 100644 --- a/libcxx/src/filesystem/posix_compat.h +++ b/libcxx/src/filesystem/posix_compat.h @@ -94,6 +94,23 @@ TimeSpec filetime_to_timespec(LARGE_INTEGER li) { return ret; } +TimeSpec filetime_to_timespec(FILETIME ft) { + LARGE_INTEGER li; + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + return filetime_to_timespec(li); +} + +FILETIME timespec_to_filetime(TimeSpec ts) { + LARGE_INTEGER li; + li.QuadPart = + ts.tv_nsec / 100 + (ts.tv_sec + FILE_TIME_OFFSET_SECS) * 10000000; + FILETIME ft; + ft.dwLowDateTime = li.LowPart; + ft.dwHighDateTime = li.HighPart; + return ft; +} + int set_errno(int e = GetLastError()) { errno = static_cast(__win_err_to_errc(e)); return -1; -- 2.25.1