From 7195dfe9b6be9dc479fbab9a0fc693ce786e7fef Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 25 Oct 2016 16:32:52 +0100 Subject: [PATCH] Handle negative times in filesystem::last_write_time * src/filesystem/ops.cc (last_write_time(const path&, file_time_type, error_code&)): Handle negative times correctly. * testsuite/experimental/filesystem/operations/last_write_time.cc: Test writing file times. From-SVN: r241522 --- libstdc++-v3/ChangeLog | 6 +++ libstdc++-v3/src/filesystem/ops.cc | 5 +++ .../filesystem/operations/last_write_time.cc | 40 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5086417d4635..11ac1062d094 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,11 @@ 2016-10-25 Jonathan Wakely + * src/filesystem/ops.cc + (last_write_time(const path&, file_time_type, error_code&)): Handle + negative times correctly. + * testsuite/experimental/filesystem/operations/last_write_time.cc: + Test writing file times. + * src/filesystem/ops.cc (do_copy_file): Report an error if source or destination is not a regular file (LWG 2712). (equivalent): Fix error handling and result when only one file exists. diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index fcf747e6a01a..32c9c5e850de 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -1100,6 +1100,11 @@ fs::last_write_time(const path& p __attribute__((__unused__)), auto s = chrono::duration_cast(d); #if _GLIBCXX_USE_UTIMENSAT auto ns = chrono::duration_cast(d - s); + if (ns < ns.zero()) // tv_nsec must be non-negative and less than 10e9. + { + --s; + ns += chrono::seconds(1); + } struct ::timespec ts[2]; ts[0].tv_sec = 0; ts[0].tv_nsec = UTIME_OMIT; diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/last_write_time.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/last_write_time.cc index dee55a53cdb1..74be4f94dda4 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/last_write_time.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/last_write_time.cc @@ -35,6 +35,8 @@ void test01() { + // read times + using time_type = std::experimental::filesystem::file_time_type; auto p = __gnu_test::nonexistent_path(); @@ -103,8 +105,46 @@ test01() #endif } +void +test02() +{ + // write times + + using time_type = std::experimental::filesystem::file_time_type; + + __gnu_test::scoped_file f; + std::error_code ec; + time_type time; + + time = last_write_time(f.path); + last_write_time(f.path, time, ec); + VERIFY( !ec ); + VERIFY( last_write_time(f.path) == time ); + + time -= std::chrono::milliseconds(1000 * 60 * 10 + 15); + last_write_time(f.path, time, ec); + VERIFY( !ec ); + VERIFY( last_write_time(f.path) == time ); + + time += std::chrono::milliseconds(1000 * 60 * 20 + 15); + last_write_time(f.path, time, ec); + VERIFY( !ec ); + VERIFY( last_write_time(f.path) == time ); + + time = time_type(); + last_write_time(f.path, time, ec); + VERIFY( !ec ); + VERIFY( last_write_time(f.path) == time ); + + time -= std::chrono::milliseconds(1000 * 60 * 10 + 15); + last_write_time(f.path, time, ec); + VERIFY( !ec ); + VERIFY( last_write_time(f.path) == time ); +} + int main() { test01(); + test02(); } -- 2.39.5