fix Issue 15803 - std.file should support sub-second file time precision on POSIX

This commit is contained in:
Vladimir Panteleev 2016-03-16 20:57:49 +00:00
parent c08032edd4
commit c3f0469b2b

View file

@ -822,6 +822,28 @@ unittest
} }
// Reads a time field from a stat_t with full precision.
version(Posix)
private SysTime statTimeToStdTime(char which)(ref stat_t statbuf)
{
auto unixTime = mixin(`statbuf.st_` ~ which ~ `time`);
long stdTime = unixTimeToStdTime(unixTime);
static if (is(typeof(mixin(`statbuf.st_` ~ which ~ `tim`))))
stdTime += mixin(`statbuf.st_` ~ which ~ `tim.tv_nsec`) / 100;
else
static if (is(typeof(mixin(`statbuf.st_` ~ which ~ `timensec`))))
stdTime += mixin(`statbuf.st_` ~ which ~ `timensec`) / 100;
else
static if (is(typeof(mixin(`statbuf.st_` ~ which ~ `time_nsec`))))
stdTime += mixin(`statbuf.st_` ~ which ~ `time_nsec`) / 100;
else
static if (is(typeof(mixin(`statbuf.__st_` ~ which ~ `timensec`))))
stdTime += mixin(`statbuf.__st_` ~ which ~ `timensec`) / 100;
return SysTime(stdTime);
}
/++ /++
Get the access and modified times of file or folder $(D name). Get the access and modified times of file or folder $(D name).
@ -863,8 +885,8 @@ void getTimes(R)(R name,
string names = null; string names = null;
cenforce(trustedStat(namez, statbuf) == 0, names, namez); cenforce(trustedStat(namez, statbuf) == 0, names, namez);
accessTime = SysTime(unixTimeToStdTime(statbuf.st_atime)); accessTime = statTimeToStdTime!'a'(statbuf);
modificationTime = SysTime(unixTimeToStdTime(statbuf.st_mtime)); modificationTime = statTimeToStdTime!'m'(statbuf);
} }
} }
@ -1217,7 +1239,7 @@ SysTime timeLastModified(R)(R name)
string names = null; string names = null;
cenforce(trustedStat(namez, statbuf) == 0, names, namez); cenforce(trustedStat(namez, statbuf) == 0, names, namez);
return SysTime(unixTimeToStdTime(statbuf.st_mtime)); return statTimeToStdTime!'m'(statbuf);
} }
} }
@ -1288,7 +1310,7 @@ SysTime timeLastModified(R)(R name, SysTime returnIfMissing)
return trustedStat(namez, statbuf) != 0 ? return trustedStat(namez, statbuf) != 0 ?
returnIfMissing : returnIfMissing :
SysTime(unixTimeToStdTime(statbuf.st_mtime)); statTimeToStdTime!'m'(statbuf);
} }
} }
@ -1312,6 +1334,35 @@ unittest
} }
// Tests sub-second precision of querying file times.
// Should pass on most modern systems running on modern filesystems.
// Exceptions:
// - FreeBSD, where one would need to first set the
// vfs.timestamp_precision sysctl to a value greater than zero.
// - OS X, where the native filesystem (HFS+) stores filesystem
// timestamps with 1-second precision.
version (FreeBSD) {} else
version (OSX) {} else
unittest
{
import core.thread;
if(exists(deleteme))
remove(deleteme);
SysTime lastTime;
foreach (n; 0..3)
{
write(deleteme, "a");
auto time = timeLastModified(deleteme);
remove(deleteme);
assert(time != lastTime);
lastTime = time;
Thread.sleep(10.msecs);
}
}
/** /**
* Determine whether the given file (or directory) exists. * Determine whether the given file (or directory) exists.
* Params: * Params:
@ -2844,21 +2895,21 @@ else version(Posix)
{ {
_ensureStatDone(); _ensureStatDone();
return SysTime(unixTimeToStdTime(_statBuf.st_ctime)); return statTimeToStdTime!'c'(_statBuf);
} }
@property SysTime timeLastAccessed() @property SysTime timeLastAccessed()
{ {
_ensureStatDone(); _ensureStatDone();
return SysTime(unixTimeToStdTime(_statBuf.st_ctime)); return statTimeToStdTime!'a'(_statBuf);
} }
@property SysTime timeLastModified() @property SysTime timeLastModified()
{ {
_ensureStatDone(); _ensureStatDone();
return SysTime(unixTimeToStdTime(_statBuf.st_mtime)); return statTimeToStdTime!'m'(_statBuf);
} }
@property uint attributes() @property uint attributes()