mirror of https://github.com/aria2/aria2
mingw: Use SetFileTime to avoid DST adjustment
parent
795a0474df
commit
cc5469c047
46
src/File.cc
46
src/File.cc
|
@ -122,9 +122,9 @@ bool File::remove()
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
namespace {
|
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 sharedMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||||
DWORD creationDisp = OPEN_EXISTING;
|
DWORD creationDisp = OPEN_EXISTING;
|
||||||
return CreateFileW(utf8ToWChar(filename).c_str(), desiredAccess, sharedMode,
|
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},
|
struct timeval times[2] = {{actime.getTimeFromEpoch(), 0},
|
||||||
{modtime.getTimeFromEpoch(), 0}};
|
{modtime.getTimeFromEpoch(), 0}};
|
||||||
return utimes(name_.c_str(), times) == 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;
|
a2utimbuf ub;
|
||||||
ub.actime = actime.getTimeFromEpoch();
|
ub.actime = actime.getTimeFromEpoch();
|
||||||
ub.modtime = modtime.getTimeFromEpoch();
|
ub.modtime = modtime.getTimeFromEpoch();
|
||||||
return a2utime(utf8ToWChar(name_).c_str(), &ub) == 0;
|
return a2utime(utf8ToWChar(name_).c_str(), &ub) == 0;
|
||||||
#endif // !HAVE_UTIMES
|
#endif // !defined(HAVE_UTIMES) && !defined(__MINGW32__)
|
||||||
}
|
}
|
||||||
|
|
||||||
Time File::getModifiedTime()
|
Time File::getModifiedTime()
|
||||||
|
|
Loading…
Reference in New Issue