<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - std::experimental::filesystem::file_time_type::min() exceeds values supported by the underlying file system"
href="https://bugs.llvm.org/show_bug.cgi?id=35990">35990</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>std::experimental::filesystem::file_time_type::min() exceeds values supported by the underlying file system
</td>
</tr>
<tr>
<th>Product</th>
<td>libc++
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>All Bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>vsapsai@apple.com
</td>
</tr>
<tr>
<th>CC</th>
<td>eric@efcs.ca, llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
</td>
</tr></table>
<p>
<div>
<pre>Created <span class=""><a href="attachment.cgi?id=19698" name="attach_19698" title="Code to test with low-level API.">attachment 19698</a> <a href="attachment.cgi?id=19698&action=edit" title="Code to test with low-level API.">[details]</a></span>
Code to test with low-level API.
std::experimental::filesystem::file_time_type::min() exceeds values supported
by the underlying file system. When you set file modification time with
filesystem::last_write_time(path, time) with min value and read it back with
filesystem::last_write_time(path), received value can be significantly
different from the supplied one.
Steps to reproduce:
1. Call
auto min_time = std::experimental::filesystem::file_time_type::min();
std::experimental::filesystem::last_write_time(path, min_time);
2. Call
auto current_time = std::experimental::filesystem::last_write_time(path);
3. Reboot machine you are running the test on.
4. Call
auto current_time2 = std::experimental::filesystem::last_write_time(path);
Expected result:
min_time, current_time, current_time2 should be equal, at least to the second.
Actual result:
Results depend on the underlying file system.
On macOS with APFS min_time != current_time, current_time == current_time2.
Inequality is detected by the test
std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp
On Ubuntu 16.04.3 with ext3 min_time == current_time, current_time !=
current_time2.
Details:
For writing and reading file modification timestamp we are using utimensat and
stat, respectively. In my testing filesystem::file_time_type::min() was -2^63
microseconds which can be expressed with `struct timespec` which has 64-bit
tv_sec and 64-bit tv_nsec. But file systems I tested don't use 128 bits to
store timestamps on the disk. One common approach seems to be using 128-bit
value while inode metadata is still in memory. That allows the test
last_write_time.pass.cpp to pass on ext3 and probably ext4. But according to
POSIX.1-2008 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/">http://pubs.opengroup.org/onlinepubs/9699919799/</a> that is not
conformant
<span class="quote">> Upon assignment, file timestamps are immediately converted to the resolution
> of the file system by truncation (i.e., the recorded time can be older than
> the actual time). For example, if the file system resolution is 1
> microsecond, then a conforming stat() must always return an st_mtim.tv_nsec
> that is a multiple of 1000. Some older implementations returned
> higher-resolution timestamps while the inode information was cached, and then
> spontaneously truncated the tv_nsec fields when they were stored to and
> retrieved from disk, but this behavior does not conform.
> - Section 11. Headers, <sys/stat.h></span >
Regardless of the POSIX standard, I think the developers expect that values in
file_time_type::min()/max() range are safe to use and won't change on their
own.
I have attached `testing.c` to test utimensat and stat directly and the results
are
On APFS:
Will update file mtime to
tv_sec = -9223372036854,
tv_nsec = 0
File mtime now is
tv_sec = -9223372036,
tv_nsec = -854775808
On ext3:
Will update file mtime to
tv_sec = -9223372036854,
tv_nsec = 0
File mtime now is
tv_sec = -9223372036854,
tv_nsec = 0
after rebooting
File mtime now is
tv_sec = 2217714954,
tv_nsec = 0</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>