mirror of https://github.com/aria2/aria2
Merge pull request #1079 from aria2/mingw-fix-remote-time-dst
mingw: Use SetFileTime to avoid DST adjustmentpull/1107/head
commit
c882ae3d9c
46
src/File.cc
46
src/File.cc
|
@ -122,9 +122,9 @@ bool File::remove()
|
|||
|
||||
#ifdef __MINGW32__
|
||||
namespace {
|
||||
HANDLE openFile(const std::string& filename)
|
||||
HANDLE openFile(const std::string& filename, bool readOnly = true)
|
||||
{
|
||||
DWORD desiredAccess = GENERIC_READ;
|
||||
DWORD desiredAccess = GENERIC_READ | (readOnly ? 0 : GENERIC_WRITE);
|
||||
DWORD sharedMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||
DWORD creationDisp = OPEN_EXISTING;
|
||||
return CreateFileW(utf8ToWChar(filename).c_str(), desiredAccess, sharedMode,
|
||||
|
@ -317,12 +317,50 @@ bool File::utime(const Time& actime, const Time& modtime) const
|
|||
struct timeval times[2] = {{actime.getTimeFromEpoch(), 0},
|
||||
{modtime.getTimeFromEpoch(), 0}};
|
||||
return utimes(name_.c_str(), times) == 0;
|
||||
#else // !HAVE_UTIMES
|
||||
#elif defined(__MINGW32__)
|
||||
auto hn = openFile(name_, false);
|
||||
if (hn == INVALID_HANDLE_VALUE) {
|
||||
auto errNum = GetLastError();
|
||||
A2_LOG_ERROR(fmt(EX_FILE_OPEN, name_.c_str(),
|
||||
util::formatLastError(errNum).c_str()));
|
||||
return false;
|
||||
}
|
||||
// Use SetFileTime because Windows _wutime takes DST into
|
||||
// consideration.
|
||||
//
|
||||
// std::chrono::time_point::time_since_epoch returns the amount of
|
||||
// time between it and epoch Jan 1, 1970. OTOH, FILETIME structure
|
||||
// expects the epoch as Jan 1, 1601. The resolution is 100
|
||||
// nanoseconds.
|
||||
constexpr auto offset = 116444736000000000LL;
|
||||
uint64_t at = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
actime.getTime().time_since_epoch())
|
||||
.count() /
|
||||
100 +
|
||||
offset;
|
||||
uint64_t mt = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
modtime.getTime().time_since_epoch())
|
||||
.count() /
|
||||
100 +
|
||||
offset;
|
||||
FILETIME att{static_cast<DWORD>(at & 0xffffffff),
|
||||
static_cast<DWORD>(at >> 32)};
|
||||
FILETIME mtt{static_cast<DWORD>(mt & 0xffffffff),
|
||||
static_cast<DWORD>(mt >> 32)};
|
||||
auto rv = SetFileTime(hn, nullptr, &att, &mtt);
|
||||
if (!rv) {
|
||||
auto errNum = GetLastError();
|
||||
A2_LOG_ERROR(fmt("SetFileTime failed, cause: %s",
|
||||
util::formatLastError(errNum).c_str()));
|
||||
}
|
||||
CloseHandle(hn);
|
||||
return rv;
|
||||
#else // !defined(HAVE_UTIMES) && !defined(__MINGW32__)
|
||||
a2utimbuf ub;
|
||||
ub.actime = actime.getTimeFromEpoch();
|
||||
ub.modtime = modtime.getTimeFromEpoch();
|
||||
return a2utime(utf8ToWChar(name_).c_str(), &ub) == 0;
|
||||
#endif // !HAVE_UTIMES
|
||||
#endif // !defined(HAVE_UTIMES) && !defined(__MINGW32__)
|
||||
}
|
||||
|
||||
Time File::getModifiedTime()
|
||||
|
|
Loading…
Reference in New Issue