Handle negative times in filesystem::last_write_time
authorJonathan Wakely <jwakely@redhat.com>
Tue, 25 Oct 2016 15:32:52 +0000 (16:32 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 25 Oct 2016 15:32:52 +0000 (16:32 +0100)
* 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
libstdc++-v3/src/filesystem/ops.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/last_write_time.cc

index 5086417..11ac106 100644 (file)
@@ -1,5 +1,11 @@
 2016-10-25  Jonathan Wakely  <jwakely@redhat.com>
 
+       * 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.
index fcf747e..32c9c5e 100644 (file)
@@ -1100,6 +1100,11 @@ fs::last_write_time(const path& p __attribute__((__unused__)),
   auto s = chrono::duration_cast<chrono::seconds>(d);
 #if _GLIBCXX_USE_UTIMENSAT
   auto ns = chrono::duration_cast<chrono::nanoseconds>(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;
index dee55a5..74be4f9 100644 (file)
@@ -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();
 }