1 // Copyright (C) 2016-2022 Free Software Foundation, Inc.
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
18 // { dg-options "-DUSE_FILESYSTEM_TS -lstdc++fs" }
19 // { dg-do run { target c++11 } }
20 // { dg-require-filesystem-ts "" }
22 // 15.25 Permissions [fs.op.last_write_time]
24 #include <experimental/filesystem>
26 #include <testsuite_fs.h>
27 #include <testsuite_hooks.h>
29 #ifdef _GLIBCXX_HAVE_FCNTL_H
32 #if _GLIBCXX_HAVE_UTIME_H
37 using time_type
= std::experimental::filesystem::file_time_type
;
39 namespace chrono
= std::chrono
;
46 auto p
= __gnu_test::nonexistent_path();
48 time_type mtime
= last_write_time(p
, ec
);
50 VERIFY( ec
== std::make_error_code(std::errc::no_such_file_or_directory
) );
54 mtime
= last_write_time(p
);
55 } catch (std::system_error
const& e
) {
61 VERIFY( ec
== std::make_error_code(std::errc::no_such_file_or_directory
) );
64 __gnu_test::scoped_file
file(p
);
66 mtime
= last_write_time(p
, ec
);
68 VERIFY( mtime
<= time_type::clock::now() );
69 VERIFY( mtime
== last_write_time(p
) );
71 auto end_of_time
= time_type::duration::max();
73 = chrono::duration_cast
<chrono::seconds
>(end_of_time
).count();
74 if (last_second
> std::numeric_limits
<std::time_t>::max())
76 puts("Range of time_t is smaller than range of chrono::file_clock, "
77 "can't test for overflow on this target.");
81 // Set mtime to a date past the maximum possible file_time_type:
82 #if _GLIBCXX_USE_UTIMENSAT
83 struct ::timespec ts
[2];
85 ts
[0].tv_nsec
= UTIME_NOW
;
86 ts
[1].tv_sec
= std::numeric_limits
<std::time_t>::max() - 1;
88 VERIFY( !::utimensat(AT_FDCWD
, p
.c_str(), ts
, 0) );
89 #elif _GLIBCXX_HAVE_UTIME_H
91 times
.modtime
= std::numeric_limits
<std::time_t>::max() - 1;
92 times
.actime
= std::numeric_limits
<std::time_t>::max() - 1;
93 VERIFY( !::utime(p
.string().c_str(), ×
) );
95 puts("No utimensat or utime, giving up.");
99 // Try to read back the impossibly-large mtime:
100 mtime
= last_write_time(p
, ec
);
101 // Some filesystems (e.g. XFS) silently truncate distant times to
102 // the time_t epochalypse, Jan 19 2038, so we won't get an error when
106 VERIFY( ec
== std::make_error_code(std::errc::value_too_large
) );
107 VERIFY( mtime
== time_type::min() );
110 puts("No overflow error, filesystem may not support 64-bit time_t.");
113 // Once more, with exceptions:
115 auto mtime2
= last_write_time(p
);
116 // If it didn't throw, expect to have read back the same value:
117 VERIFY( mtime2
== mtime
);
118 } catch (std::experimental::filesystem::filesystem_error
const& e
) {
119 // If it did throw, expect the error_code to be the same:
120 VERIFY( e
.code() == ec
);
121 VERIFY( e
.path1() == p
);
126 bool approx_equal(time_type file_time
, time_type expected
)
128 auto delta
= expected
- file_time
;
129 if (delta
< delta
.zero())
131 return delta
< chrono::seconds(1);
139 const std::error_code bad_ec
= make_error_code(std::errc::invalid_argument
);
140 __gnu_test::scoped_file f
;
145 time
= last_write_time(f
.path
);
146 last_write_time(f
.path
, time
, ec
);
148 VERIFY( approx_equal(last_write_time(f
.path
), time
) );
151 time
-= chrono::milliseconds(1000 * 60 * 10 + 15);
152 last_write_time(f
.path
, time
, ec
);
154 VERIFY( approx_equal(last_write_time(f
.path
), time
) );
157 time
+= chrono::milliseconds(1000 * 60 * 20 + 15);
158 last_write_time(f
.path
, time
, ec
);
160 VERIFY( approx_equal(last_write_time(f
.path
), time
) );
164 last_write_time(f
.path
, time
, ec
);
166 VERIFY( approx_equal(last_write_time(f
.path
), time
) );
169 time
-= chrono::milliseconds(1000 * 60 * 10 + 15);
170 last_write_time(f
.path
, time
, ec
);
172 VERIFY( approx_equal(last_write_time(f
.path
), time
) );